package com.ruoyi.orm.ds;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Map;

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;

import com.baomidou.dynamic.datasource.config.properties.DyDSProperties;
import com.baomidou.dynamic.datasource.creator.DataSourceProperty;
import com.isolar.comps.core.utils.SpringUtils;
import com.isolar.comps.mybatis.exception.DsDbException;
import com.zaxxer.hikari.HikariDataSource;

import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * Spring JDBC 实时数据库访问
 */
@Slf4j
public class DynamicDBUtil {

    /**
     * 获取数据源
     *
     * @param dbSource
     * @return
     */
    private static HikariDataSource getJdbcDataSource(final DynamicDataSourceModel dbSource) {
    	HikariDataSource dataSource = new HikariDataSource();
        String driverClassName = dbSource.getDbDriver();
        String url = dbSource.getDbUrl();
        String dbUser = dbSource.getDbUsername();
        String dbPassword = dbSource.getDbPassword();
        
        dataSource.setDriverClassName(driverClassName);
        dataSource.setJdbcUrl(url);
        dataSource.setUsername(dbUser);
        dataSource.setPassword(dbPassword);
        //dataSource.setValidationQuery("SELECT 1 FROM DUAL");
        log.info("******************************************");
        log.info("*                                        *");
        log.info("*====【"+dbSource.getCode()+"】=====HikariDataSource连接池已启用 ====*");
        log.info("*                                        *");
        log.info("******************************************");
        return dataSource;
    }

    /**
     * 通过 dbKey ,获取数据源
     *
     * @param dbKey
     * @return
     */
    public static HikariDataSource getDbSourceByDbKey(final String dbKey) {
        //获取多数据源配置
        DynamicDataSourceModel dbSource = DataSourceCachePool.getCacheDynamicDataSourceModel(dbKey);
        //先判断缓存中是否存在数据库链接
        HikariDataSource cacheDbSource = DataSourceCachePool.getCacheBasicDataSource(dbKey);
        if (cacheDbSource != null && !cacheDbSource.isClosed()) {
            log.debug("--------getDbSourceBydbKey------------------从缓存中获取DB连接-------------------");
            return cacheDbSource;
        } else {
        	HikariDataSource dataSource = getJdbcDataSource(dbSource);
            if(dataSource!=null && dataSource.isRunning()){
                DataSourceCachePool.putCacheBasicDataSource(dbKey, dataSource);
            }else{
                throw new DsDbException("动态数据源连接失败，dbKey："+dbKey);
            }
            log.info("--------getDbSourceBydbKey------------------创建DB数据库连接-------------------");
            return dataSource;
        }
    }

    /**
     * 关闭数据库连接池
     *
     * @param dbKey
     * @return
     */
    public static void closeDbKey(final String dbKey) {
    	HikariDataSource dataSource = getDbSourceByDbKey(dbKey);
        try {
            if (dataSource != null && !dataSource.isClosed()) {
                dataSource.getConnection().commit();
                dataSource.getConnection().close();
                dataSource.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }


    public static JdbcTemplate getJdbcTemplate(String dbKey) {
    	HikariDataSource dataSource = getDbSourceByDbKey(dbKey);
        return new JdbcTemplate(dataSource);
    }

    /**
     * 根据数据源获取NamedParameterJdbcTemplate
     * @param dbKey
     * @return
     */
    public static NamedParameterJdbcTemplate getNamedParameterJdbcTemplate(String dbKey) {
    	HikariDataSource dataSource = getDbSourceByDbKey(dbKey);
        return new NamedParameterJdbcTemplate(dataSource);
    }

    
    /**
     * 根据数据源key获取DataSourceProperty
     * @param sourceKey
     * @return
     */
    public static DataSourceProperty getDataSourceProperty(String sourceKey){
    	DyDSProperties prop = SpringUtils.getApplicationContext().getBean(DyDSProperties.class);
        Map<String, DataSourceProperty> map = prop.getDatasource();
        DataSourceProperty db = (DataSourceProperty)map.get(sourceKey);
        return db;
    }

    /**
     * 根据sourceKey 获取数据源连接
     * @param sourceKey
     * @return
     * @throws SQLException
     */
    public static Connection getDataSourceConnect(String sourceKey) throws SQLException {
        if (StrUtil.isEmpty(sourceKey)) {
            sourceKey = "master";
        }
        DyDSProperties prop = SpringUtils.getApplicationContext().getBean(DyDSProperties.class);
        Map<String, DataSourceProperty> map = prop.getDatasource();
        DataSourceProperty db = (DataSourceProperty)map.get(sourceKey);
        if(db==null){
            return null;
        }
        DriverManagerDataSource ds = new DriverManagerDataSource();
        ds.setDriverClassName(db.getDriverClassName());
        ds.setUrl(db.getUrl());
        ds.setUsername(db.getUsername());
        ds.setPassword(db.getPassword());
        return ds.getConnection();
    }
}
